import { Injectable, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, Between } from 'typeorm';
import * as XLSX from 'xlsx';
import { Match } from './entities/match.entity';
import { Betting } from './entities/betting.entity';
import { CreateMatchDto } from './dto/create-match.dto';
import { UpdateMatchDto } from './dto/update-match.dto';
import { QueryMatchDto } from './dto/query-match.dto';
import { ImportExcelDto } from './dto/import-excel.dto';
import { UpdateScoreDto } from './dto/update-score.dto';
import { ExcelDateUtil } from './utils/excel-date.util';
import { ExcelValidatorUtil, BatchValidationResult } from './utils/excel-validator.util';
import { ImportResult, ImportStatistics, ImportResponse } from './interfaces/import-result.interface';
import { calculateDateRange, getCurrentTimeDescription, createRecommendationFilter } from './utils/date-filter.util';

@Injectable()
export class MatchesService {
  constructor(
    @InjectRepository(Match)
    private readonly matchRepository: Repository<Match>,
    @InjectRepository(Betting)
    private readonly bettingRepository: Repository<Betting>,
  ) {}

  /**
   * 创建比赛
   */
  async create(createMatchDto: CreateMatchDto): Promise<Match> {
    const { bettings, ...matchData } = createMatchDto;
    
    // 创建比赛
    const match = this.matchRepository.create({
      ...matchData,
      matchTime: new Date(createMatchDto.matchTime),
    });
    const savedMatch = await this.matchRepository.save(match);

    // 创建投注选项
    if (bettings && bettings.length > 0) {
      const bettingEntities = bettings.map(betting => 
        this.bettingRepository.create({
          ...betting,
          matchId: savedMatch.id,
        })
      );
      await this.bettingRepository.save(bettingEntities);
    }

    return this.findOne(savedMatch.id);
  }

  /**
   * 分页查询比赛列表
   */
  async findAll(queryDto: QueryMatchDto) {
    const { 
      page = 1, 
      pageSize = 10, 
      leagueName, 
      homeTeam, 
      awayTeam, 
      startTime, 
      endTime,
      jingcaiNumber,
      beidanNumber,
      dateFilter,
      recommendationStatus 
    } = queryDto;

    // 调试日志：记录查询参数
    console.log('查询参数:', {
      startTime,
      endTime,
      dateFilter,
      recommendationStatus,
      page,
      pageSize
    });

    const queryBuilder = this.matchRepository
      .createQueryBuilder('match')
      .leftJoinAndSelect('match.bettings', 'betting')
      .orderBy('match.matchTime', 'ASC');

    // 添加筛选条件
    if (leagueName) {
      queryBuilder.andWhere('match.leagueName LIKE :leagueName', { 
        leagueName: `%${leagueName}%` 
      });
    }

    if (homeTeam) {
      queryBuilder.andWhere('match.homeTeam LIKE :homeTeam', { 
        homeTeam: `%${homeTeam}%` 
      });
    }

    if (awayTeam) {
      queryBuilder.andWhere('match.awayTeam LIKE :awayTeam', { 
        awayTeam: `%${awayTeam}%` 
      });
    }

    if (jingcaiNumber) {
      queryBuilder.andWhere('betting.jingcaiNumber = :jingcaiNumber', { 
        jingcaiNumber 
      });
    }

    if (beidanNumber) {
      queryBuilder.andWhere('betting.beidanNumber = :beidanNumber', { 
        beidanNumber 
      });
    }

    // 处理时间筛选逻辑
    if (dateFilter) {
      const dateRange = calculateDateRange(dateFilter);
      queryBuilder.andWhere('match.matchTime BETWEEN :startTime AND :endTime', {
        startTime: dateRange.startTime,
        endTime: dateRange.endTime,
      });
      console.log(getCurrentTimeDescription());
      console.log(dateRange.description);
    } else if (startTime && endTime) {
      queryBuilder.andWhere('match.matchTime BETWEEN :startTime AND :endTime', {
        startTime: new Date(startTime),
        endTime: new Date(endTime),
      });
    } else if (startTime) {
      queryBuilder.andWhere('match.matchTime >= :startTime', {
        startTime: new Date(startTime),
      });
    } else if (endTime) {
      queryBuilder.andWhere('match.matchTime <= :endTime', {
        endTime: new Date(endTime),
      });
    }

    // 分页
    const [data, total] = await queryBuilder
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    // 处理推荐状态筛选
    let filteredData = data;
    let filteredTotal = total;
    
    if (recommendationStatus) {
      const recommendationFilter = createRecommendationFilter(recommendationStatus);
      
      // 如果需要推荐状态筛选，需要重新查询所有数据进行筛选
      // 这是因为推荐状态基于关联的投注数据，无法直接在SQL中高效筛选
      // 重新构建查询条件，确保包含所有之前的筛选条件
      const allDataQueryBuilder = this.matchRepository
        .createQueryBuilder('match')
        .leftJoinAndSelect('match.bettings', 'betting')
        .orderBy('match.matchTime', 'ASC');

      // 重新添加所有筛选条件
      if (leagueName) {
        allDataQueryBuilder.andWhere('match.leagueName LIKE :leagueName', { 
          leagueName: `%${leagueName}%` 
        });
      }

      if (homeTeam) {
        allDataQueryBuilder.andWhere('match.homeTeam LIKE :homeTeam', { 
          homeTeam: `%${homeTeam}%` 
        });
      }

      if (awayTeam) {
        allDataQueryBuilder.andWhere('match.awayTeam LIKE :awayTeam', { 
          awayTeam: `%${awayTeam}%` 
        });
      }

      if (jingcaiNumber) {
        allDataQueryBuilder.andWhere('betting.jingcaiNumber = :jingcaiNumber', { 
          jingcaiNumber 
        });
      }

      if (beidanNumber) {
        allDataQueryBuilder.andWhere('betting.beidanNumber = :beidanNumber', { 
          beidanNumber 
        });
      }

      // 重新添加时间筛选条件
      if (dateFilter) {
        const dateRange = calculateDateRange(dateFilter);
        allDataQueryBuilder.andWhere('match.matchTime BETWEEN :startTime AND :endTime', {
          startTime: dateRange.startTime,
          endTime: dateRange.endTime,
        });
      } else if (startTime && endTime) {
        allDataQueryBuilder.andWhere('match.matchTime BETWEEN :startTime AND :endTime', {
          startTime: new Date(startTime),
          endTime: new Date(endTime),
        });
      } else if (startTime) {
        allDataQueryBuilder.andWhere('match.matchTime >= :startTime', {
          startTime: new Date(startTime),
        });
      } else if (endTime) {
        allDataQueryBuilder.andWhere('match.matchTime <= :endTime', {
          endTime: new Date(endTime),
        });
      }
      
      const allData = await allDataQueryBuilder.getMany();
      
      // 调试：分析推荐状态分布
      const recommendedCount = allData.filter(item => {
        if (!item.bettings || !Array.isArray(item.bettings)) {
          return false;
        }
        return item.bettings.some((betting: any) => {
          const recommendedResult = betting.recommendedResult;
          return recommendedResult !== null && 
                 recommendedResult !== undefined && 
                 recommendedResult !== '' && 
                 !(Array.isArray(recommendedResult) && recommendedResult.length === 0);
        });
      }).length;
      
      const pendingCount = allData.filter(item => {
        if (!item.bettings || !Array.isArray(item.bettings)) {
          return true;
        }
        return item.bettings.every((betting: any) => {
          const recommendedResult = betting.recommendedResult;
          return recommendedResult === null || 
                 recommendedResult === undefined || 
                 recommendedResult === '' || 
                 (Array.isArray(recommendedResult) && recommendedResult.length === 0);
        });
      }).length;
      
      const partialRecommendedCount = allData.filter(item => {
        if (!item.bettings || !Array.isArray(item.bettings)) {
          return false;
        }
        const hasRecommended = item.bettings.some((betting: any) => {
          const recommendedResult = betting.recommendedResult;
          return recommendedResult !== null && 
                 recommendedResult !== undefined && 
                 recommendedResult !== '' && 
                 !(Array.isArray(recommendedResult) && recommendedResult.length === 0);
        });
        const hasNotRecommended = item.bettings.some((betting: any) => {
          const recommendedResult = betting.recommendedResult;
          return recommendedResult === null || 
                 recommendedResult === undefined || 
                 recommendedResult === '' || 
                 (Array.isArray(recommendedResult) && recommendedResult.length === 0);
        });
        return hasRecommended && hasNotRecommended;
      }).length;
      
      console.log(`推荐状态分析: 总数=${allData.length}, 已推荐=${recommendedCount}, 未推荐=${pendingCount}, 部分推荐=${partialRecommendedCount}`);
      
      filteredData = allData.filter(recommendationFilter.filterCondition);
      filteredTotal = filteredData.length;
      
      // 手动分页
      const startIndex = (page - 1) * pageSize;
      const endIndex = startIndex + pageSize;
      filteredData = filteredData.slice(startIndex, endIndex);
    }

    return {
      data: filteredData,
      total: filteredTotal,
      page,
      pageSize,
      totalPages: Math.ceil(filteredTotal / pageSize),
    };
  }

  /**
   * 根据ID查询比赛详情
   */
  async findOne(id: number): Promise<Match> {
    const match = await this.matchRepository.findOne({
      where: { id },
      relations: ['bettings'],
    });

    if (!match) {
      throw new BadRequestException('比赛不存在');
    }

    return match;
  }

  /**
   * 更新比赛
   */
  async update(id: number, updateMatchDto: UpdateMatchDto): Promise<Match> {
    const match = await this.findOne(id);
    const { bettings, ...matchData } = updateMatchDto;

    // 更新比赛基本信息
    if (updateMatchDto.matchTime) {
      matchData.matchTime = updateMatchDto.matchTime;
    }
    
    await this.matchRepository.update(id, matchData);

    // 如果有投注选项更新，先删除旧的再创建新的
    if (bettings) {
      await this.bettingRepository.delete({ matchId: id });
      
      if (bettings.length > 0) {
        const bettingEntities = bettings.map(betting => 
          this.bettingRepository.create({
            ...betting,
            matchId: id,
          })
        );
        await this.bettingRepository.save(bettingEntities);
      }
    }

    return this.findOne(id);
  }

  /**
   * 删除比赛
   */
  async remove(id: number): Promise<void> {
    const match = await this.findOne(id);
    
    // 删除关联的投注选项
    await this.bettingRepository.delete({ matchId: id });
    
    // 删除比赛
    await this.matchRepository.remove(match);
  }

  /**
   * 批量删除比赛
   */
  async removeBatch(ids: number[]): Promise<void> {
    // 删除关联的投注选项
    await this.bettingRepository
      .createQueryBuilder()
      .delete()
      .where('matchId IN (:...ids)', { ids })
      .execute();
    
    // 删除比赛
    await this.matchRepository.delete(ids);
  }

  /**
   * 导入Excel文件
   * @param buffer Excel文件缓冲区
   * @returns 导入结果
   */
  async importExcel(buffer: Buffer): Promise<ImportResponse> {
    const startTime = new Date();
    // 验证buffer参数
    if (!buffer) {
      throw new BadRequestException('文件缓冲区为空，请确保文件上传成功');
    }
    
    try {
      // 解析Excel文件
      const workbook = XLSX.read(buffer, { type: 'buffer' });
      
      // 检查工作簿是否有工作表
      if (!workbook.SheetNames || workbook.SheetNames.length === 0) {
        throw new BadRequestException('Excel文件中没有找到工作表');
      }
      
      const sheetName = workbook.SheetNames[0];
      const worksheet = workbook.Sheets[sheetName];
      
      // 检查工作表是否存在
      if (!worksheet) {
        throw new BadRequestException('无法读取Excel工作表内容');
      }
      
      const jsonData = XLSX.utils.sheet_to_json(worksheet) as any[];

      if (!jsonData || jsonData.length === 0) {
        throw new BadRequestException('Excel文件为空或格式不正确');
      }

      // 解析Excel数据
      const parsedData: ImportExcelDto[] = [];
      const parseErrors: string[] = [];
      
      jsonData.forEach((row, index) => {
        try {
          const importData = this.parseExcelRow(row);
          parsedData.push(importData);
        } catch (error) {
          parseErrors.push(`第${index + 2}行数据解析失败: ${error.message}`);
        }
      });

      // 数据验证
      const validationResult: BatchValidationResult = ExcelValidatorUtil.validateBatchData(parsedData);

      // 过滤出有效数据
      const validData = parsedData.filter((_, index) => validationResult.results[index].isValid);
      
      // 重复校验：根据external_id检查是否已存在
      const duplicateWarnings: string[] = [];
      const uniqueData: ImportExcelDto[] = [];
      
      for (const importData of validData) {
        if (importData.externalId) {
          // 检查数据库中是否已存在相同external_id的比赛
          const existingMatch = await this.matchRepository.findOne({
            where: { externalId: importData.externalId }
          });
          
          if (existingMatch) {
            duplicateWarnings.push(`跳过重复数据: ID=${importData.externalId}, 比赛=${importData.leagueName} ${importData.homeTeam} vs ${importData.awayTeam}`);
            continue;
          }
        }
        uniqueData.push(importData);
      }
      
      const results = {
        success: 0,
        failed: parseErrors.length + validationResult.invalidCount,
        errors: [...parseErrors, ...validationResult.allErrors],
        warnings: [...validationResult.allWarnings, ...duplicateWarnings],
        totalProcessed: jsonData.length,
        validCount: uniqueData.length,
        duplicateCount: duplicateWarnings.length,
      };

      // 按比赛分组（开赛时间、赛事、主队、客队相同的为一场比赛）
      const matchGroups = new Map<string, ImportExcelDto[]>();
      
      uniqueData.forEach((importData) => {
        const matchKey = `${importData.matchTime}_${importData.leagueName}_${importData.homeTeam}_${importData.awayTeam}`;
        
        if (!matchGroups.has(matchKey)) {
          matchGroups.set(matchKey, []);
        }
        matchGroups.get(matchKey)!.push(importData);
      });

      // 处理每个比赛组
      for (const [matchKey, rows] of matchGroups) {
        try {
          await this.processMatchGroup(rows);
          results.success++;
        } catch (error) {
          results.failed++;
          results.errors.push(`比赛组 ${matchKey} 处理失败: ${error.message}`);
        }
      }

      const endTime = new Date();
      const duration = endTime.getTime() - startTime.getTime();
      
      // 构建统计信息
      const statistics: ImportStatistics = {
        startTime,
        endTime,
        duration,
        fileSize: buffer.length,
        worksheetCount: workbook.SheetNames.length,
        dataRowCount: jsonData.length,
        matchGroupCount: matchGroups.size,
      };
      
      // 构建完整响应
      const response: ImportResponse = {
        ...results,
        statistics,
        isSuccess: results.errors.length === 0,
        message: results.errors.length === 0 
          ? `✅ Excel导入成功！处理了 ${results.success} 个比赛组，耗时 ${duration}ms`
          : `⚠️  Excel导入部分成功，${results.success} 个成功，${results.failed} 个失败`
      };
      

      
      return response;
    } catch (error) {
      throw new BadRequestException(`Excel导入失败: ${error.message}`);
    }
  }

  /**
   * 解析Excel行数据
   */
  private parseExcelRow(row: any): ImportExcelDto {
    return {
      jingcaiNumber: this.parseStringValue(row['竞彩编号'] || row['jingcaiNumber']),
      beidanNumber: this.parseStringValue(row['北单编号'] || row['beidanNumber']),
      matchTime: this.parseStringValue(row['开赛时间'] || row['matchTime']),
      leagueName: this.parseStringValue(row['赛事'] || row['leagueName']),
      homeTeam: this.parseStringValue(row['主队'] || row['homeTeam']),
      awayTeam: this.parseStringValue(row['客队'] || row['awayTeam']),
      jingcaiSingle: this.parseStringValue(row['竞彩单关'] || row['jingcaiSingle']),
      jingcaiHandicap: this.parseNumberValue(row['竞彩让球'] || row['jingcaiHandicap']),
      beidanHandicap: this.parseNumberValue(row['北单让球'] || row['beidanHandicap']),
      winOdds: this.parseNumberValue(row['胜'] || row['winOdds']),
      drawOdds: this.parseNumberValue(row['平'] || row['drawOdds']),
      loseOdds: this.parseNumberValue(row['负'] || row['loseOdds']),
      externalId: this.parseStringValue(row['ID'] || row['externalId']),
      boldRecommendation: this.parseStringValue(row['胆推荐'] || row['boldRecommendation']),
      homeWinRate: this.parseNumberValue(row['主队胜率'] || row['homeWinRate']),
      awayWinRate: this.parseNumberValue(row['客队胜率'] || row['awayWinRate']),
      remarks: this.parseStringValue(row['备注'] || row['remarks']),
      recommendedResult: this.parseArrayValue(row['推荐结果'] || row['recommendedResult']),
      homeScore: this.parseNumberValue(row['主比分'] || row['homeScore']),
      awayScore: this.parseNumberValue(row['客比分'] || row['awayScore']),
      matchResult: this.parseStringValue(row['赛果'] || row['matchResult']),
      predictionHit: this.parseBooleanValue(row['预测命中'] || row['predictionHit']),
    };
  }

  /**
   * 处理比赛组数据
   * @param rows 比赛组数据
   */
  private async processMatchGroup(rows: ImportExcelDto[]): Promise<void> {
    if (!rows || rows.length === 0) {
      throw new Error('比赛组数据为空');
    }

    const firstRow = rows[0];
    
    // 验证必要字段（这里应该已经通过验证，但为了安全再次检查）
    if (!firstRow.matchTime || !firstRow.leagueName || !firstRow.homeTeam || !firstRow.awayTeam) {
      throw new Error('缺少必要的比赛信息（开赛时间、赛事、主队、客队）');
    }

    // 使用工具类解析日期
    let matchDate: Date;
    try {
      matchDate = ExcelDateUtil.parseExcelDate(firstRow.matchTime);
    } catch (error) {
      throw new Error(`日期解析失败: ${firstRow.matchTime} - ${error.message}`);
    }

    // 检查比赛是否已存在
    const existingMatch = await this.matchRepository.findOne({
      where: {
        matchTime: matchDate,
        leagueName: firstRow.leagueName,
        homeTeam: firstRow.homeTeam,
        awayTeam: firstRow.awayTeam,
      },
    });

    let match: Match;
    
    if (existingMatch) {
      // 更新现有比赛
      await this.matchRepository.update(existingMatch.id, {
        externalId: firstRow.externalId || existingMatch.externalId,
        boldRecommendation: firstRow.boldRecommendation || existingMatch.boldRecommendation,
        homeWinRate: firstRow.homeWinRate || existingMatch.homeWinRate,
        awayWinRate: firstRow.awayWinRate || existingMatch.awayWinRate,
        remarks: firstRow.remarks || existingMatch.remarks,
      });
      
      // 删除现有投注选项
      await this.bettingRepository.delete({ matchId: existingMatch.id });
      
      // 重新获取更新后的比赛数据
      const updatedMatch = await this.matchRepository.findOne({ where: { id: existingMatch.id } });
      if (!updatedMatch) {
        throw new Error('更新比赛后无法找到比赛记录');
      }
      match = updatedMatch;
    } else {
      // 创建新比赛
      match = this.matchRepository.create({
        matchTime: matchDate,
        leagueName: firstRow.leagueName,
        homeTeam: firstRow.homeTeam,
        awayTeam: firstRow.awayTeam,
        externalId: firstRow.externalId,
        boldRecommendation: firstRow.boldRecommendation || 'none',
        homeWinRate: firstRow.homeWinRate,
        awayWinRate: firstRow.awayWinRate,
        remarks: firstRow.remarks,
      });
      match = await this.matchRepository.save(match);
    }

    // 创建投注选项
    const validBettingRows = rows.filter(row => {
      // 至少要有一个赔率值且不为0
      const hasValidOdds = (row.winOdds && row.winOdds > 0) || 
                          (row.drawOdds && row.drawOdds > 0) || 
                          (row.loseOdds && row.loseOdds > 0);
      
      return hasValidOdds;
    });
    
    if (validBettingRows.length === 0) {
      throw new Error('没有有效的投注选项数据');
    }
    
    const bettingEntities = validBettingRows.map((row) => {
      return this.bettingRepository.create({
        matchId: match.id,
        jingcaiNumber: row.jingcaiNumber,
        beidanNumber: row.beidanNumber,
        jingcaiSingle: row.jingcaiSingle,
        jingcaiHandicap: row.jingcaiHandicap,
        beidanHandicap: row.beidanHandicap,
        winOdds: row.winOdds,
        drawOdds: row.drawOdds,
        loseOdds: row.loseOdds,
        recommendedResult: row.recommendedResult,
        homeScore: row.homeScore,
        awayScore: row.awayScore,
        matchResult: row.matchResult,
        predictionHit: row.predictionHit,
      });
    });

    await this.bettingRepository.save(bettingEntities);
  }

  /**
   * 解析字符串值
   */
  private parseStringValue(value: any): string | undefined {
    if (value === null || value === undefined || value === '' || value === 'undefined' || value === 'null') {
      return undefined;
    }
    const str = String(value).trim();
    return str === '' ? undefined : str;
  }

  /**
   * 解析数字值
   */
  private parseNumberValue(value: any): number | undefined {
    if (value === null || value === undefined || value === '' || value === 'undefined' || value === 'null') {
      return undefined;
    }
    
    // 处理字符串类型的数字
    const str = String(value).trim();
    if (str === '') {
      return undefined;
    }
    
    const num = Number(str);
    return isNaN(num) ? undefined : num;
  }

  /**
   * 解析数组值
   */
  private parseArrayValue(value: any): string[] | undefined {
    if (value === null || value === undefined || value === '' || value === 'undefined' || value === 'null') {
      return undefined;
    }
    
    // 如果已经是数组
    if (Array.isArray(value)) {
      return value.filter(item => item && typeof item === 'string');
    }
    
    // 如果是字符串，尝试解析JSON或按逗号分割
    const str = String(value).trim();
    if (str === '' || str === '[]') {
      return [];
    }
    
    try {
      // 尝试解析JSON格式
      const parsed = JSON.parse(str);
      if (Array.isArray(parsed)) {
        return parsed.filter(item => item && typeof item === 'string');
      }
    } catch {
      // JSON解析失败，按逗号分割
      return str.split(',').map(item => item.trim()).filter(item => item !== '');
    }
    
    return undefined;
  }

  /**
   * 解析布尔值
   */
  private parseBooleanValue(value: any): boolean | undefined {
    if (value === null || value === undefined || value === '' || value === 'undefined' || value === 'null') {
      return undefined;
    }
    
    // 如果已经是布尔值
    if (typeof value === 'boolean') {
      return value;
    }
    
    // 字符串转换
    const str = String(value).trim().toLowerCase();
    if (str === 'true' || str === '1' || str === 'yes' || str === '是') {
      return true;
    }
    if (str === 'false' || str === '0' || str === 'no' || str === '否') {
      return false;
    }
    
    return undefined;
  }

  /**
   * 比分更新Excel导入
   */
  async importScoreUpdate(buffer: Buffer): Promise<ImportResponse> {
    const startTime = new Date();
    
    // 验证buffer参数
    if (!buffer) {
      throw new BadRequestException('文件缓冲区为空，请确保文件上传成功');
    }
    
    try {
      // 解析Excel文件
      const workbook = XLSX.read(buffer, { type: 'buffer' });
      
      if (!workbook.SheetNames || workbook.SheetNames.length === 0) {
        throw new BadRequestException('Excel文件中没有找到工作表');
      }
      
      const sheetName = workbook.SheetNames[0];
      const worksheet = workbook.Sheets[sheetName];
      
      if (!worksheet) {
        throw new BadRequestException('无法读取Excel工作表内容');
      }
      
      const jsonData = XLSX.utils.sheet_to_json(worksheet) as any[];

      if (!jsonData || jsonData.length === 0) {
        throw new BadRequestException('Excel文件为空或格式不正确');
      }

      // 解析Excel数据
      const parsedData: UpdateScoreDto[] = [];
      const parseErrors: string[] = [];
      
      jsonData.forEach((row, index) => {
        try {
          const scoreData = this.parseScoreUpdateRow(row);
          parsedData.push(scoreData);
        } catch (error) {
          parseErrors.push(`第${index + 2}行数据解析失败: ${error.message}`);
        }
      });

      const results = {
        success: 0,
        failed: parseErrors.length,
        errors: [...parseErrors],
        warnings: [],
        totalProcessed: jsonData.length,
        validCount: parsedData.length,
        duplicateCount: 0,
      };

      // 处理比分更新
      for (const scoreData of parsedData) {
        try {
          await this.updateMatchScore(scoreData);
          results.success++;
        } catch (error) {
          results.failed++;
          results.errors.push(`比分更新失败: ${error.message}`);
        }
      }

      const endTime = new Date();
      const duration = endTime.getTime() - startTime.getTime();
      
      // 构建统计信息
      const statistics: ImportStatistics = {
        startTime,
        endTime,
        duration,
        fileSize: buffer.length,
        worksheetCount: workbook.SheetNames.length,
        dataRowCount: jsonData.length,
        matchGroupCount: parsedData.length,
      };
      
      // 构建完整响应
      const response: ImportResponse = {
        ...results,
        statistics,
        isSuccess: results.errors.length === 0,
        message: results.errors.length === 0 
          ? `✅ 比分更新导入成功！处理了 ${results.success} 条记录，耗时 ${duration}ms`
          : `⚠️  比分更新导入部分成功，${results.success} 条成功，${results.failed} 条失败`
      };
      

      
      return response;
    } catch (error) {
      throw new BadRequestException(`比分更新Excel导入失败: ${error.message}`);
    }
  }

  /**
   * 解析比分更新Excel行数据
   */
  private parseScoreUpdateRow(row: any): UpdateScoreDto {
    // 修复0值处理问题：使用nullish coalescing operator (??) 替代逻辑或 (||)
    // 这样可以确保0值不会被跳过
    const homeScore = this.parseNumberValue(row['主比分'] ?? row['homeScore']);
    const awayScore = this.parseNumberValue(row['客比分'] ?? row['awayScore']);
    const matchResult = this.parseStringValue(row['赛果'] ?? row['matchResult']);
    
    return {
      jingcaiNumber: this.parseStringValue(row['竞彩编号'] || row['jingcaiNumber']),
      beidanNumber: this.parseStringValue(row['北单编号'] || row['beidanNumber']),
      matchTime: this.parseStringValue(row['开赛时间'] || row['matchTime']),
      leagueName: this.parseStringValue(row['赛事'] || row['leagueName']),
      homeTeam: this.parseStringValue(row['主队'] || row['homeTeam']),
      awayTeam: this.parseStringValue(row['客队'] || row['awayTeam']),
      jingcaiSingle: this.parseStringValue(row['竞彩单关'] || row['jingcaiSingle']),
      jingcaiHandicap: this.parseNumberValue(row['竞彩让球'] || row['jingcaiHandicap']),
      beidanHandicap: this.parseNumberValue(row['北单让球'] || row['beidanHandicap']),
      winOdds: this.parseNumberValue(row['胜'] || row['winOdds']),
      drawOdds: this.parseNumberValue(row['平'] || row['drawOdds']),
      loseOdds: this.parseNumberValue(row['负'] || row['loseOdds']),
      externalId: this.parseStringValue(row['ID'] || row['externalId']),
      boldRecommendation: this.parseStringValue(row['胆推荐'] || row['boldRecommendation']),
      homeWinRate: this.parseNumberValue(row['主队胜率'] || row['homeWinRate']),
      awayWinRate: this.parseNumberValue(row['客队胜率'] || row['awayWinRate']),
      remarks: this.parseStringValue(row['备注'] || row['remarks']),
      // 比分更新的新字段 - 只有当Excel中有数据时才设置，否则为undefined
      homeScore,
      awayScore,
      matchResult,
    };
  }

  /**
   * 更新比赛比分
   */
  private async updateMatchScore(scoreData: UpdateScoreDto): Promise<void> {
    // 验证必要字段
    if (!scoreData.matchTime || !scoreData.leagueName || !scoreData.homeTeam || !scoreData.awayTeam) {
      throw new Error('缺少必要的比赛信息（开赛时间、赛事、主队、客队）');
    }

    // 检查是否有需要更新的数据（注意：0是有效的比分值）
    const hasScoreData = (scoreData.homeScore !== undefined && scoreData.homeScore !== null) || 
                         (scoreData.awayScore !== undefined && scoreData.awayScore !== null);
    const hasResultData = scoreData.matchResult !== undefined && scoreData.matchResult !== null && scoreData.matchResult !== '';
    
    if (!hasScoreData && !hasResultData) {
      return;
    }

    // 解析日期
    let matchDate: Date;
    try {
      matchDate = ExcelDateUtil.parseExcelDate(scoreData.matchTime);
    } catch (error) {
      throw new Error(`日期解析失败: ${scoreData.matchTime} - ${error.message}`);
    }

    // 构建查询条件，精确匹配所有字段
    const whereConditions: any = {
      match: {
        matchTime: matchDate,
        leagueName: scoreData.leagueName,
        homeTeam: scoreData.homeTeam,
        awayTeam: scoreData.awayTeam,
      }
    };

    // 添加可选的匹配字段
    if (scoreData.jingcaiNumber) {
      whereConditions.jingcaiNumber = scoreData.jingcaiNumber;
    }
    if (scoreData.beidanNumber) {
      whereConditions.beidanNumber = scoreData.beidanNumber;
    }
    if (scoreData.jingcaiSingle) {
      whereConditions.jingcaiSingle = scoreData.jingcaiSingle;
    }
    if (scoreData.jingcaiHandicap !== undefined && scoreData.jingcaiHandicap !== null) {
      whereConditions.jingcaiHandicap = scoreData.jingcaiHandicap;
    }
    if (scoreData.beidanHandicap !== undefined && scoreData.beidanHandicap !== null) {
      whereConditions.beidanHandicap = scoreData.beidanHandicap;
    }
    if (scoreData.winOdds !== undefined && scoreData.winOdds !== null) {
      whereConditions.winOdds = scoreData.winOdds;
    }
    if (scoreData.drawOdds !== undefined && scoreData.drawOdds !== null) {
      whereConditions.drawOdds = scoreData.drawOdds;
    }
    if (scoreData.loseOdds !== undefined && scoreData.loseOdds !== null) {
      whereConditions.loseOdds = scoreData.loseOdds;
    }

    // 查找精确匹配的投注选项
    const matchingBettings = await this.bettingRepository.find({
      where: whereConditions,
      relations: ['match'],
    });

    if (!matchingBettings || matchingBettings.length === 0) {
      throw new Error(`未找到匹配的投注选项: ${scoreData.leagueName} ${scoreData.homeTeam} vs ${scoreData.awayTeam} (${scoreData.matchTime})`);
    }

    // 更新匹配的投注选项
    for (const betting of matchingBettings) {
      // 构建更新数据对象，只包含有数据的字段
      const updateData: any = {};
      
      // 分别检查每个比分字段（注意：0是有效的比分值）
      if (scoreData.homeScore !== undefined && scoreData.homeScore !== null) {
        updateData.homeScore = scoreData.homeScore;
      }
      if (scoreData.awayScore !== undefined && scoreData.awayScore !== null) {
        updateData.awayScore = scoreData.awayScore;
      }
      
      if (hasResultData) {
        updateData.matchResult = scoreData.matchResult;
        // 只有当有赛果数据时才计算预测命中
        updateData.predictionHit = this.calculatePredictionHit(betting.recommendedResult || [], scoreData.matchResult || '');
      }
      
      if (Object.keys(updateData).length > 0) {
        await this.bettingRepository.update(betting.id, updateData);
      }
    }
  }

  /**
   * 计算预测命中情况
   * @param recommendedResult 推荐结果
   * @param matchResult 实际赛果
   * @returns 是否命中
   */
  private calculatePredictionHit(
    recommendedResult: string | string[],
    matchResult: string,
  ): boolean {
    if (!recommendedResult || !matchResult) {
      return false;
    }

    // 赛果中文转英文映射
    const resultMapping = {
      '胜': 'win',
      '平': 'draw',
      '负': 'lose'
    };

    // 将实际赛果转换为英文
    const englishMatchResult = resultMapping[matchResult] || matchResult;

    // 如果推荐结果是数组
    if (Array.isArray(recommendedResult)) {
      return recommendedResult.includes(englishMatchResult);
    }

    // 如果推荐结果是字符串
    if (typeof recommendedResult === 'string') {
      // 直接匹配
      if (recommendedResult === englishMatchResult) {
        return true;
      }

      // 检查组合推荐（如"胜平"、"平负"）
      const combinations = {
        '胜平': ['win', 'draw'],
        '平负': ['draw', 'lose'],
        '胜负': ['win', 'lose'], // 可能的组合
        'win': ['win'],
        'draw': ['draw'],
        'lose': ['lose']
      };

      if (combinations[recommendedResult]) {
        return combinations[recommendedResult].includes(englishMatchResult);
      }

      return false;
    }

    return false;
  }
}